package com.share.util.common;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 高性能JSON工具类（基于Jackson）
 * 特性：
 * 1. 线程安全的ObjectMapper缓存
 * 2. 支持Java8日期时间API
 * 3. 完善的异常处理
 * 4. 可配置的序列化规则
 */
public class JSONUtils {
    private static final ConcurrentHashMap<String, ObjectMapper> MAPPER_CACHE = new ConcurrentHashMap<>();
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("Asia/Shanghai");

    // 获取默认配置的ObjectMapper（线程安全）
    public static ObjectMapper getDefaultMapper() {
        return MAPPER_CACHE.computeIfAbsent("default", k -> {
            ObjectMapper mapper = new ObjectMapper();
            configMapper(mapper, DEFAULT_DATE_FORMAT, DEFAULT_TIME_ZONE);
            return mapper;
        });
    }

    // 配置ObjectMapper
    private static void configMapper(ObjectMapper mapper, String dateFormat, TimeZone timeZone) {
        // 基础配置
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 日期时间处理
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.setDateFormat(new SimpleDateFormat(dateFormat));
        mapper.setTimeZone(timeZone);
    }

    //=============== 基础序列化/反序列化 ===============//

    public static String toJsonStr(Object obj) {
        return serialize(obj, getDefaultMapper());
    }

    public static <T> T toBean(String jsonStr, Class<T> clazz) {
        return deserialize(jsonStr, clazz, getDefaultMapper());
    }

    //=============== 高级功能 ===============//

    /**
     * 支持泛型的反序列化
     * 示例：List<User> users = fromJson(json, new TypeReference<List<User>>() {});
     */
    public static <T> T toBean(String jsonStr, TypeReference<T> typeReference) {
        try {
            return getDefaultMapper().readValue(jsonStr, typeReference);
        } catch (JsonProcessingException e) {
            throw new JsonException("JSON反序列化失败", e);
        }
    }

    /**
     * 美化输出的JSON字符串
     */
    public static String toPrettyJson(Object obj) {
        try {
            return getDefaultMapper().writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new JsonException("JSON美化输出失败", e);
        }
    }

    /**
     * 动态修改日期格式的序列化
     */
    public static String toJsonStrWithDateFormat(Object obj, String dateFormat) {
        ObjectMapper mapper = new ObjectMapper();
        configMapper(mapper, dateFormat, DEFAULT_TIME_ZONE);
        return serialize(obj, mapper);
    }

    //=============== 底层方法 ===============//

    private static String serialize(Object obj, ObjectMapper mapper) {
        if (obj == null) return null;
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new JsonException("JSON序列化失败", e);
        }
    }

    private static <T> T deserialize(String jsonStr, Class<T> clazz, ObjectMapper mapper) {
        if (jsonStr == null || jsonStr.isEmpty()) return null;
        try {
            return mapper.readValue(jsonStr, clazz);
        } catch (JsonProcessingException e) {
            throw new JsonException("JSON反序列化失败", e);
        }
    }

    //=============== 自定义异常 ===============//
    public static class JsonException extends RuntimeException {
        public JsonException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}